import { GLTFMeshTaskInfo, Stage, TransformNode } from 'babylon-lib/index';
import { ISceneInfo } from '../../global/common-type'
import { AssetManager } from '../asset-manager';
import { PhysicsManager } from '../../physics/physicsManager';
import { Mesh } from '@babylonjs/core/Meshes/mesh';
import { Helper } from 'babylon-lib/tool/helper';
import { PBRMaterial, Texture } from '@babylonjs/core';


/**
 * 在场景模型中任意空物体上挂载自定义属性 reflectionTexture，值为以反射纹理作为diffuse/albedo纹理的mesh名称
 */
const REFLECTION_TEXTURE_MESH_KEY = "reflectionTexture";


class GalleryResolver {

    private _originalData: ISceneInfo;
    private _stage: Stage;

    constructor(data: ISceneInfo, stage: Stage, onResolved?: { (resolver: GalleryResolver): void }) {
        console.log('resolve scene', data)
        this._originalData = data;
        this._stage = stage;
        this.loadAssets().then((result) => {
            this.generateStaticRigid();
            this.setLightAndReflection();
            if (onResolved) onResolved(this);
        }).catch((err) => {
            console.error('加载展馆数据时遇到了错误', err);
        });;
    }

    private async loadAssets(): Promise<void> {
        const urls: string[] = [];
        if (this._originalData.sceneModelUrl) urls.push(this._originalData.sceneModelUrl);
        if (this._originalData.sceneRigidUrl) urls.push(this._originalData.sceneRigidUrl);
        await AssetManager.load(urls, this._stage.loader(this._stage.mainScene), undefined, undefined, undefined, () => { }, (err) => {
            console.error('展馆文件加载失败', err);
        });
    }

    private getReflectionTexture(modelInfo:GLTFMeshTaskInfo):Texture|null{
        let paramObj: TransformNode | null = null;
        for (const node of modelInfo.loadedTransformNodes!) {
            if (node.metadata && node.metadata.gltf && node.metadata.gltf.extras) {
                paramObj = node;
                break;
            }
        }
        let envTexture: Texture | null = null;
        if (paramObj) {
            const reflectionName = paramObj.metadata.gltf.extras[REFLECTION_TEXTURE_MESH_KEY];
            if (reflectionName) {
                const m = Helper.nodeInArray(reflectionName, modelInfo.loadedMeshes!, undefined, true) as Mesh;
                if (m) envTexture = (m.material as PBRMaterial).albedoTexture as Texture;
            }
        }
        if (envTexture) {
            envTexture.coordinatesMode = Texture.EQUIRECTANGULAR_MODE;
            return envTexture;
        }else{
            console.warn('reflection texture not set');
        }
        return null;
    }

    private setLightAndReflection(): void {
        const modelInfo = AssetManager.getAsset(this._originalData.sceneModelUrl!) as GLTFMeshTaskInfo;

        const envTexture = this.getReflectionTexture(modelInfo);

        modelInfo.loadedMeshes!.forEach(mesh => {
            mesh.isPickable = false;
            const mat = mesh.material as PBRMaterial;
            if (mat) {
                if (envTexture) mat.reflectionTexture = envTexture;
                mat.backFaceCulling = true;
            }
            if (mat && mat.emissiveTexture) {
                const lightMap = mat.emissiveTexture;
                mat.emissiveTexture = null;
                lightMap.coordinatesIndex = 1;
                lightMap.level = 2;
                mat.lightmapTexture = lightMap;
                mat.useLightmapAsShadowmap = true;

                mesh.freezeWorldMatrix();
                mesh.doNotSyncBoundingInfo = true;
            }
        });
    }

    private generateStaticRigid(): void {
        if (!this._originalData.sceneRigidUrl) {
            console.error('没有设置静态刚体模型路径，无法生成静态刚体');
            return;
        }
        const modelInfo = AssetManager.getAsset(this._originalData.sceneRigidUrl!) as GLTFMeshTaskInfo;
        if (!modelInfo) {
            console.error('没有找到静态刚体模型，无法生成静态刚体');
            return;
        }

        PhysicsManager.setStaticAggregateBox(...modelInfo.loadedMeshes as Mesh[]);

    }

}


export { GalleryResolver };